﻿#region Using

using System;
using System.Reflection;
using Commons.Diagnostics;
using SAPbouiCOM;
using SapFramework.Extension.Database;
using DiCompany = SAPbobsCOM.Company;

#endregion

namespace SapFramework.Application.Connections
{
    /// <summary>
    /// Classe que realiza a conexão com SAP Business One, seja pela DI ou pela UI Api
    /// </summary>
    public class SboConnection
    {
        /// <summary>
        /// Global que guarda o Assembly de SAPbouiCOM.
        /// </summary>
        public static readonly Assembly srUiAssembly = Assembly.GetAssembly( typeof( SAPbouiCOM.Application ) );
        /// <summary>
        /// Global que guarda o Assembly de SAPbobsCOM.
        /// </summary>
        public static readonly Assembly srDiAssembly = Assembly.GetAssembly( typeof( SAPbobsCOM.Company ) );

        #region DiConnectionType enum

        /// <summary>
        /// Tipo de conexão a ser realizado com a DI API.
        /// </summary>
        public enum DiConnectionType
        {
            /// <summary>
            /// Não realiza conexão com a base de dados da SAP.
            /// </summary>
            None,
            /// <summary>
            /// Realiza a conexão utilizando o método antigo (Cookies + Context).
            /// </summary>
            OldMethod,
            /// <summary>
            /// Recupera a conexão com a base de dados da SAP diretamente da UI API.
            /// </summary>
            NewMethod,
        }

        #endregion

        /// <summary>
        /// String de conexão padrão
        /// </summary>
        public const string cConnectionString = "0030002C0030002C00530041005000420044005F00440061007400650076002C0050004C006F006D0056004900490056";

        /// <summary>
        /// Objeto para ligação com a UI API do SAP Business One.
        /// </summary>
        private readonly SboGuiApi mSboClient = new SboGuiApi();

        /// <summary>
        /// Construtor que realiza a conexão, via DI API apenas, com uma base do SAP Business One.
        /// </summary>
        /// <param name="aDiCompany">Um objeto do tipo Company que já esteja completamente parâmetrizado</param>
        public SboConnection( DiCompany aDiCompany )
        {
            Contract.Requires.NotNull( () => aDiCompany );

            Database = aDiCompany;

            if ( !Database.Connected )
            {
                Database.Connect();
                Database.ExceptionOnFailure();
            }
        }

        /// <summary>
        /// Construtor que realiza a conexão com a Interface do SAP Business One. Possui um parâmetro para conectar também na DI API.
        /// </summary>
        /// <param name="aAddOnIdentifier">String de identificação do AddOn</param>
        /// <param name="aConnectionString">String de conexão com o Client do SAP Business One</param>
        /// <param name="aDiConnetionType">Tipo de conexão a ser realizado com a DI API</param>
        public SboConnection( string aAddOnIdentifier, string aConnectionString = cConnectionString, DiConnectionType aDiConnetionType = DiConnectionType.NewMethod )
        {
            mSboClient.AddonIdentifier = aAddOnIdentifier;

            mSboClient.Connect( aConnectionString );

            Interface = mSboClient.GetApplication();

            switch ( aDiConnetionType )
            {
                case DiConnectionType.None:
                    break;

                case DiConnectionType.OldMethod:
                    ConnectDiViaOldMethod();
                    break;

                case DiConnectionType.NewMethod:
                    Database = Interface.Company.GetDICompany();
                    break;

                default:
                    throw new ArgumentOutOfRangeException( "aDiConnetionType" );
            }
        }

        /// <summary>
        /// Referência para o objeto de aplicação do SAP Business One. Nele se encontra toda a parte visual do programa.
        /// </summary>
        public SAPbouiCOM.Application Interface { get; private set; }

        /// <summary>
        /// Referência para um objeto de conexão com uma base do SAP Business One.
        /// </summary>
        public DiCompany Database { get; private set; }

        /// <summary>
        /// Realiza o processo de conexão com a DI API pelo método antigo.
        /// </summary>
        private void ConnectDiViaOldMethod()
        {
            Contract.Requires.NotNull( () => Interface );

            Database = new DiCompany();

            string lCookie = Database.GetContextCookie();

            string lConnectionContext = Interface.Company.GetConnectionContext( lCookie );

            Database.SetSboLoginContext( lConnectionContext );
            Database.ExceptionOnFailure();

            Database.Connect();
            Database.ExceptionOnFailure();
        }
    }
}